﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Xml.Linq;

namespace SharePointUtilitiesForDevelopers
{
    /// <summary>
    /// A domain class that represents a SharePoint list item.
    /// </summary>
    [ReadOnly(true)]
    [DefaultProperty("Title")]
    public class SharePointListItem
    {

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        [Description("The list item id.")]
        public string Id { get; set; }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        [Description("The list item title.")]
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets the definition.
        /// </summary>
        /// <value>The definition.</value>
        [Description("The XML definition of the list item.")]
        public XElement Definition { get; set; }
 
        /// <summary>
        /// Gets or sets the item values.
        /// </summary>
        /// <value>The values.</value>
        [Description("The list item values.")]
        public Dictionary<string, string> Values
        {
            get; set;
        }
    }

    /// <summary>
    /// Extension methods for <see cref="SharePointListItem"/> objects.
    /// </summary>
    public static class SharePointListItemExtensionMethods
    {
        /// <summary>
        /// Returns the list items as a batch update command for the 
        /// Lists.UpdateListItems method.
        /// </summary>
        /// <param name="listItems">The list items.</param>
        /// <param name="listVersion">The list version.</param>
        /// <returns>XML batch update.</returns>
        public static XElement ToBatchUpdateXElement(
            this IEnumerable<SharePointListItem> listItems,
            string listVersion)
        {
            XNamespace ns = string.Empty;
            var batch = new XElement(
                ns + "Batch",
                new XAttribute("OnError", "Continue"),
                new XAttribute("PreCalc", "TRUE"),
                new XAttribute("ListVersion", listVersion));
            var id = 1;

            foreach (var listItem in listItems)
            {
                var method = new XElement(
                    "Method",
                    new XAttribute("ID", id.ToString()),
                    new XAttribute("Cmd", "Update"));
                batch.Add(method);
                foreach (var fieldName in listItem.Values.Keys)
                {
                    var field = new XElement(
                        "Field",
                        new XAttribute("Name", fieldName)) { Value = listItem.Values[fieldName] };
                    method.Add(field);
                }

                id++;
            }

            return batch;
        }

        /// <summary>
        /// Returns the list items as a batch update command for the 
        /// Lists.UpdateListItems method.
        /// </summary>
        /// <param name="listItems">The list items.</param>
        /// <param name="listVersion">The list version.</param>
        /// <returns>XML batch update.</returns>
        public static XElement ToBatchDeleteXElement(
            this IEnumerable<SharePointListItem> listItems, 
            string listVersion)
        {
            XNamespace ns = string.Empty;
            var batch = new XElement(
                ns + "Batch", 
                new XAttribute("OnError", "Continue"), 
                new XAttribute("PreCalc", "TRUE"),
                new XAttribute("ListVersion", listVersion));
            var id = 1;

            foreach(var listItem in listItems)
            {
                var method = new XElement(
                    "Method", 
                    new XAttribute("ID", id.ToString()),
                    new XAttribute("Cmd", "Delete"));
                batch.Add(method);

                var field = new XElement(
                    "Field",
                    new XAttribute("Name", "ID")) { Value = listItem.Id };
                method.Add(field);

                id++;
            }

            return batch;
        }

        /// <summary>
        /// Returns the list as a <see cref="DataTable"/>.
        /// </summary>
        /// <param name="listItems">The list items.</param>
        /// <returns>A <see cref="DataTable"/>.</returns>
        public static DataTable ToDataTable(this IEnumerable<SharePointListItem> listItems)
        {
            // Create the table
            var table = new DataTable();

            // Add each item
            foreach(var listItem in listItems)
            {
                // Add the row
                var row = table.Rows.Add();

                // Get the keys (fields)
                var keys = listItem.Values.Keys.ToList();
                keys.Sort();

                // Enumerate the fields in the list item
                foreach (var key in keys)
                {
                    // If the table doesn't have a column for the field, add it
                    if(!table.Columns.Contains(key))
                    {
                        table.Columns.Add(key);
                    }

                    // Set the column value
                    row[key] = listItem.Values[key];
                }
            }

            return table;
        }
    }
}
